/**
 * Copyright (C) 2010 DustedPixels.com
 */
package com.dustedpixels.cirt;

import com.dustedpixels.cirt.model.machine.spectrum.ZxSpectrum48;

/**
 * AppletRunnable
 *
 * @author Michal Pociecha-Los (micapolos@gmail.com)
 */
public final class CirtRunnables {
  /**
   * Creates and returns new runnable which will run in the applet thread.
   * 
   * @return
   */
  public static Runnable newRunnable(
      final Runnable onRepaint,
      final ZxSpectrum48 zx, 
      final byte[] videoBytes) {
    return new Runnable() {
      public void run() {
        long startMillis = System.currentTimeMillis();
        long targetMillis = startMillis;
        boolean isRunning = true;
        while (isRunning) {
          long frameStartMillis = System.currentTimeMillis();
          
          // Give emulation 20ms of time = 50FPS
          targetMillis += 20;
          
          // update zx spectrum circuit
          synchronized (videoBytes) {
            final int frameCycles = 448 * 312;
            for (int i = 0; i < frameCycles; i++) {
              zx.update();
            }
          }
          
          // Repaint the component
          onRepaint.run();
          
          // Sync to frame rate.
          long time = System.currentTimeMillis();
          long slackTime = targetMillis - time;
          if (slackTime > 0) {
            try {
              Thread.sleep(slackTime);
            } catch (InterruptedException e) {
              if (Thread.interrupted()) {
                isRunning = false;
              }
            }
          }
          
          System.out.println("Updated in: " + (time - frameStartMillis));
        }
      }
    };
  }
}
